/**
 * request 网络请求工具
 * 更详细的 api 文档: https://github.com/umijs/umi-request
 */
import {extend} from 'umi-request';
import {message} from 'antd';
import {assign, omit, isFunction, isObject, isString, isEmpty} from 'lodash-es';
import {urlEncode} from 'jh-utils';
import {jhError} from "jh-lib";

export const loginApis = {
    pswLogin: '/api/login',
    phoneLogin: '/api/pc/sms/login/open/sms_login',
    logout: '/api/logout'
};

/**
 * 请求超时时间5分钟
 * @type {number}
 */
const reqTimeOut = (1000 * 60) * 5;
// const  reqTimeOut = 500;

/**
 * 异常处理程序
 */
const errorHandler = (error) => {
    // console.log('errorHandler', error);
    if (error && error.message && -1 !== error.message.indexOf('timeout')) {
        // '请求超时，稍后再试'
        message.error('504');
        return null;
    }

    const {request, response, data} = error;
    // console.log('response', response, data);
    if (response && 401 != response.status) { // 401 标识登录过期，会在 isLogin 中处理；所以这里不做提示。
        let errorText = '';

        if (data && data.states && data.states.message) {
            errorText = `${data.states.message} - ${response.status}`;

        } else {
            errorText = 'Request fail' || response.statusText;
        }

        if (isString(data)) {
            error.data = {errorText, data}

        } else if (data) {
            data.errorText = errorText;
        }
        // const { status } = response;
        if (false !== request.options.needTip) {
            message.error(`请求失败: ${errorText}`, 2);
        }

    }
    return error;
};

export const isLogin = (res, showTip = true) => {
    let noLogined = res && res.response && 401 == res.response.status; // http 401 错误时，表示登录过期

    // console.log('noLogined', noLogined);

    // if (showTip && noLogined) {
    //   // 处理登录过期逻辑。弹出登录过期提示，然后弹出登录弹框
    //   window.dealLoginTimeout && window.dealLoginTimeout();
    //
    // } else {
    //   return !noLogined;
    // }
    return true;
};

export const failHandler = (response, isReturn) => {
    let errMsg = '';
    if (isObject(response) && 'undefined' !== typeof response.status) {
        if (200 !== parseInt(response.status)) {
            errMsg = `请求失败:${response.status} ${isString(response.data) ? response.data : ''}`;
        }
    } else if (response.errorText) {
        errMsg = response.errorText;

    } else if (isEmpty(response)) {
        errMsg = '请求失败';
    }
    if (true === isReturn) {
        return errMsg;
    }

    if (!isEmpty(errMsg)) {
        if (errMsg.length > 20) {
            jhError({content: errMsg});
        } else {
            message.error(errMsg);
        }
    }
    return response;
};

/**
 * 配置request请求时的默认参数
 */
export const request = extend({
    // prefix: process.env.apiPrefix,
    errorHandler, // 默认错误处理
    credentials: 'include', // 默认请求是否带上cookie
    getResponse: true,
});

request.use(async (ctx, next) => {
    const {req} = ctx;
    const {options} = req;
    let api = req.url;

    // if (isEmpty(api) || (isString(api) && 0 !== api.indexOf('/api'))) {
    //     return Promise.resolve();
    // }

    await next();

    const {res} = ctx;

    // 统一将接口的错误码字符串 200 转换为数字 200
    if (isObject(res) && res.data && 'undefined' !== typeof res.data.status) {
        if ('200' == res.data.status) {
            res.data.status = parseInt(res.data.status);
        }

        if (options && options.signal) {
            options.signal.noAbort = true;
        }
    }
});

function beforeReq({options}) {
    let hide;
    if (options && true === options.needLoading) {
        hide = message.loading('loading', 0);
    }
    return {hide};
}

function afterReq({api, res, options, hide}) {
    isFunction(hide) && hide();

    // 如果没有登陆，则跳转到登录页
    isLogin(res);

    let httpStatus = res && res.response ? res.response.status : null;
    let rsp = res ? res.data : null;

    // 错误提示
    if (200 === httpStatus && options && false !== options.needTip) {
        failHandler(rsp, false, res);
    }

    return res ? res.data : null;
}

export default request;

//---------------------------
//-- 异步请求常用方法
//---------------------------

/**
 * get 请求
 * @param api api 地址
 * @param params （可选）参数
 * @param options （可选）request 的 options
 * @returns {Promise<any>}
 */
export const reqGet = (api, params = {}, options = {}) => {
    let fOption = {
        headers: {Accept: 'application/json;charset=UTF-8'},
        params: {
            ...omit(params, ['signal', 'needLoading', 'needTip']),
        },
        timeout: reqTimeOut,
        ...assign({signal: params.signal, needLoading: params.needLoading, needTip: params.needTip}, options),
    };
    let {hide} = beforeReq({options: fOption});

    return request.get(api, fOption).then((res) => (
        afterReq({api, res, options: fOption, hide})
    )).catch(e => {
        console.error('e', e);
    });

};

/**
 * post 提交 json 数据，Content-type=application/json
 * @param api String api 地址
 * @param data Object 提交数据对象
 * @param options Object （可选）request 的 options
 * @returns {Promise<any>}
 */
export const jsonPost = (api, data = {}, options = {}) => {
    let fOption = {
        method: 'post',
        timeout: reqTimeOut,
        // requestType: 'form',
        data: {
            ...omit(data, ['signal', 'noLoading', 'needLoading', 'needTip']),
        },
        ...assign({signal: data.signal, needLoading: data.needLoading, needTip: data.needTip}, options),
    };
    let {hide} = beforeReq({options: fOption});

    return request(api, fOption).then((res) => (
        afterReq({api, res, options: fOption, hide})
    )).catch(e => {
        console.error('e', e);
    });
};

/**
 * post 提交 Form Data 数据，Content-type=application/x-www-form-urlencoded
 * @param api String api 地址
 * @param data Object 提交数据对象
 * @param options Object （可选）request 的 options
 * @returns {Promise<any>}
 */
export const formPost = (api, data = {}, options = {}) => {
    const fData = {
        ...omit(data, ['signal', 'needLoading', 'needTip']),
        // locale: 'en-US' !== window.localStorage.getItem('umi_locale') ? 'zh' : 'en', // 加上国际化参数

    };
    let fOption = {
        method: 'post',
        timeout: reqTimeOut,
        headers: {
            'Content-type': 'application/json;charset=UTF-8',
            // 'Content-type':'application/x-www-form-urlencoded',
            Accept: 'application/json;charset=UTF-8',
        },
        body: urlEncode(fData),
        // data: { ...omit(data, ['signal', 'needLoading']) },
        ...assign({signal: data.signal, needLoading: data.needLoading, needTip: data.needTip}, options),
    };
    let {hide} = beforeReq({options: fOption});

    return request(api, fOption).then((res) => (
        afterReq({api, res, options: fOption, hide})
    )).catch(e => {
        console.error('e', e);
    });
};

//---------------------------
//-- 异步请求控制器
//---------------------------

/**
 * new 异步请求控制器
 */
export const newAbortCtrl = () => {
    if ('AbortController' in window) {
        return new window.AbortController();
    } else {
        console.warn('浏览器不支持 AbortController，将无法中止异步请求');
        return {};
    }
};

/**
 * 终断 request 请求
 * @param abortCtrl
 */
export const abortFetch = (abortCtrl) => {
    if ('AbortController' in window) {

        if (abortCtrl && true !== abortCtrl.signal.noAbort) {
            abortCtrl.abort();
        }
    } else {
        console.warn('浏览器不支持 AbortController，将无法中止异步请求');
        return {};
    }
};
